package zack.project.domain.activity.service.quota.rule.impl;

import zack.project.domain.activity.adapter.repository.IActivityRepository;
import zack.project.domain.activity.model.entity.ActivityCountEntity;
import zack.project.domain.activity.model.entity.ActivityEntity;
import zack.project.domain.activity.model.entity.ActivitySkuEntity;
import zack.project.domain.activity.model.valobj.ActivitySkuStockKeyVO;
import zack.project.domain.activity.service.armory.IActivityDispatch;
import zack.project.domain.activity.service.quota.rule.AbstractActionChain;
import zack.project.types.enums.ResponseCode;
import zack.project.types.exception.AppException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @author A1793
 * sku库存过滤
 */
@Slf4j
@Component("activity_sku_stock_action")
public class ActivitySkuStockActionChain extends AbstractActionChain {

    @Resource
    private IActivityDispatch activityDispatch;

    @Resource
    private IActivityRepository activityRepository;

    /**
     * 尝试扣减缓存sku库存并加次数锁（如果sku库存扣减到了0则发mq消息，监听到了之后清空数据库sku库存余量和redis延迟队列中扣减库存消息）
     * 然后发送sku库存扣减消息异步修改数据库表{raffle_activity_sku}
     * @param activitySkuEntity
     * @param activityEntity
     * @param activityCountEntity
     * @return
     */
    @Override
    public boolean action(ActivitySkuEntity activitySkuEntity,
                          ActivityEntity activityEntity,
                          ActivityCountEntity activityCountEntity) {
        log.info("活动责任链-sku库存校验开始。");
        //   扣减sku库存，先在缓存中根据"activity_sku_stock_count_key_#{sku}"进行decr扣减操作，
        //   再设置一个"activity_sku_stock_count_key_#{sku}_#{surplus}"的抢占锁，并且当该sku商品对应的库存为0时，
        //   会发送一个ActivitySkuStockZeroMessageEvent消息
        boolean status = activityDispatch.subtractionActivitySkuStock(activitySkuEntity.getSku(),
                activityEntity.getEndDateTime());
        //缓存中的库存扣减成功，向redis中的延迟延迟队列投放一个sku库存扣减的消息，
        // UpdateActivitySkuStockJob执行定时任务时会从对应的阻塞队列中获取消息消费，
        // 根据ActivitySkuStockKeyVO的sku更新数据库表{raffle_activity_sku}
        if (status) {
            activityRepository.activitySkuStockConsumeSendQueue(ActivitySkuStockKeyVO.builder()
                    .sku(activitySkuEntity.getSku())
                    .activityId(activityEntity.getActivityId())
                    .build());
            return true;
        }
        throw new AppException(ResponseCode.ACTIVITY_SKU_STOCK_ERROR.getCode(),
                ResponseCode.ACTIVITY_SKU_STOCK_ERROR.getInfo());
    }
}
